package br.com.puertorico.common.utils;

import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.Locale;

public class ReflectionUtils {

	public static Object extractFieldValue(Field field, Object obj) {
		try {
			String fieldName = field.getName();
			fieldName = fieldName.substring(0, 1).toUpperCase(
					Locale.getDefault())
					+ fieldName.substring(1);

			Method m = null;
			if (field.getType().equals(boolean.class)
					|| field.getType().equals(Boolean.class)) {
				String method = "is" + fieldName;
				if (containsMethod(method, obj)) {
					m = obj.getClass().getMethod(method, new Class[] {});
				}
			}
			if (m == null) {
				String method = "get" + fieldName;
				m = obj.getClass().getMethod(method, new Class[] {});
			}

			Object result = m.invoke(obj);
			return result;
			/*
			 * possiveis exceptions SecurityException, NoSuchMethodException,
			 * IllegalArgumentException, IllegalAccessException,
			 * InvocationTargetException
			 */
		} catch (Exception e) {
			throw new IllegalArgumentException();
		}
	}

	public static void setFieldValue(Field field, Object bean, Object param) {
		try {
			String fieldName = field.getName();
			fieldName = fieldName.substring(0, 1).toUpperCase(
					Locale.getDefault())
					+ fieldName.substring(1);

			Method m = null;

			String method = "set" + fieldName;
			m = bean.getClass().getMethod(method,
					new Class[] { findMethodReturnType(fieldName, bean) });
			m.invoke(bean, param);
		} catch (Exception e) {
			throw new IllegalArgumentException();
		}
	}

	private static Class<?> findMethodReturnType(String fieldName, Object bean)
			throws SecurityException, NoSuchMethodException {
		Class<?> ret = null;
		try {
			ret = bean.getClass().getMethod("get" + fieldName).getReturnType();
		} catch (Exception e) {
			// pode ser boolean
			ret = bean.getClass().getMethod("is" + fieldName).getReturnType();
		}
		return ret;
	}

	public static boolean containsMethod(String method, Object obj) {
		for (Method m : obj.getClass().getMethods()) {
			if (m.toGenericString().indexOf(
					obj.getClass().getSimpleName() + "." + method) != -1) {
				return true;
			}
		}
		return false;
	}
}
